package na.learn.java.simpleprogs;

import na.learn.java.simpleprogs.NestedOuterClass.MemberInterface.InsideMemberInterface;
import na.learn.java.simpleprogs.NestedOuterClass.StaticInnerClass.NonStaticInnerClassLevel2;
import na.learn.java.simpleprogs.NestedOuterClass.StaticInnerClass.StaticInnerClassLevel2;

// Outermost class
public class NestedOuterClass {
	private String state = "OuterState";

	private String outerClassName = "NestedOuterClass";

	public NestedOuterClass() {
		System.out.println("Constructor of " + outerClassName);
	}

	//	Non Static Inner Class
	class InnerOne {

		private String state = "OuterState";

		// non static inner class can not have static members
		// static int value;

		static final int age = 3; // Although static final members are allowed

		public InnerOne() {
			System.out.println("Enclosing class: " + outerClassName);
			System.out.println("Constructor of InnerOne.");

			doIt();

			System.out.println("Enclosing State: "
					+ NestedOuterClass.this.state + "\n My State: " + state);
		}

		public void doIt() {
			MemberInterface memberint = new MemberInterfaceImpl();

		}
	}

	// Static Inner Class 
	static class StaticInnerClass {

		public String state = "OuterState";

		public StaticInnerClass() {
			//	 Cannot use ourter class variable  System.out.println("Enclosing class: " + outerClassName); //
			System.out.println("Enclosing class: "
					+ new NestedOuterClass().getOuterClassName());
			System.out.println("Constructor of StaticInnerClass.");

		}

		//static interface in a static member inner class 
		interface InterfaceInsideInnerClass {
			String name = "name";

		}

		static class StaticInnerClassLevel2 {
			private String state = "OuterState";

			public StaticInnerClassLevel2() {
				System.out.println("Enclosing State: " + "\n My State: "
						+ state);
			}

		}

		class NonStaticInnerClassLevel2 {
			private String state = "NonStaticInnerClassLevel2";

			public NonStaticInnerClassLevel2() {
				System.out
						.println("Inside NonStaticInnerClassLevel2, Enclosing State: "
								+ StaticInnerClass.this.state
								+ "\n My State: "
								+ state);
			}

		}
	}

	// Extended interface of static inner interface
	interface Extended_InterfaceInsideInnerClass extends
			StaticInnerClass.InterfaceInsideInnerClass {

	}

	// Inner Interface
	interface MemberInterface {
		String COLOR = "WHITE";

		public class InsideMemberInterface {

			public InsideMemberInterface() {
				System.out.println("Constructor of InsideMemberInterface.");
				doIt();
			}

			public void doIt() {
				System.out.println("Hello!!! I am here.");
			}
		}

	}

	// Inner Inner Interface 2
	interface MemberInterfaceTwo {
		String COLOR = "WHITE";
	}

	//Inner Interface Child
	interface MemberInterfaceChild extends MemberInterface, MemberInterfaceTwo {
		//   COLOR is ambigous   String MyColor = COLOR;		

	}

	// Implementation of Member Interface
	class MemberInterfaceImpl implements MemberInterface {
		public MemberInterfaceImpl() {
			System.out.println("Constructor of MemberInterfaceImpl. ");
			InsideMemberInterface inside = new InsideMemberInterface();
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		NestedOuterClass outer = new NestedOuterClass();

		InnerOne nonStInner1 = outer.new InnerOne();

		StaticInnerClass stInner = new StaticInnerClass();

		MemberInterface memberInterace = outer.new MemberInterfaceImpl();

		StaticInnerClassLevel2 stInnerClassL2One = new StaticInnerClassLevel2();

		StaticInnerClassLevel2 stInnerClassL2 = new StaticInnerClass.StaticInnerClassLevel2();
		
		NonStaticInnerClassLevel2 nonStInL2 = stInner.new NonStaticInnerClassLevel2();

	}

	public void testLocals() {
		//  No local Interfaces are allowed  interface LocalInterface {	}		
	}

	public String getOuterClassName() {
		return outerClassName;
	}

}
